package xyz.lwm.lazycat.annotation;

import xyz.lwm.lazycat.beans.BeanDesign;
import xyz.lwm.lazycat.beans.Condition;
import xyz.lwm.lazycat.utility.StringUtil;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 当 bean 存在时，才启用该 design 到 beans 容器
 *
 * @author lwm
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@Conditional(ConditionalOnBean.OnBeanCondition.class)
public @interface ConditionalOnBean {

    /**
     * Bean name, 优先匹配 name
     */
    String name() default "";

    /**
     * Bean class
     */
    Class<?> value() default Void.class;

    /**
     * on bean 条件判断
     */
    class OnBeanCondition implements Condition {

        @Override
        public boolean matches(Context ctx, BeanDesign<?> design) {

            ConditionalOnBean onBean = design.getAnnotations()
                    .getAnnotation(ConditionalOnBean.class);
            String name = onBean.name();
            Class<?> clz = onBean.value();
            if (StringUtil.isNotBlank(name)) {
                return ctx.getDesignMap().containsKey(name);

            } else if (clz != Void.class &&
                    clz != Object.class &&
                    clz != design.getType()) {
                return ctx.getDesignMap().values().stream()
                        .anyMatch(d -> clz.isAssignableFrom(d.getType()));

            } else {
                return false;
            }

        }

    }

}
